<?php

namespace App\Kuafu\Order\Service;


use App\Kuafu\Common\Service\CommonService;
use App\Kuafu\CouponExt\Enum\CouponExtEnum;
use App\Kuafu\CouponExt\Model\OrderCouponExtSplitModel;
use App\Kuafu\CouponPackage\Model\CouponPackageOrderModel;
use App\Kuafu\CouponPackage\Service\CouponPackageService;
use App\Kuafu\Customer\Service\CustomerPlatformService;
use App\Kuafu\Mqtt\Service\MqttService;
use App\Kuafu\Mybank\Service\CalcBrokerage\MybankCalcOrderBrokerageService;
use App\Kuafu\Mybank\Service\MybankBrokerageService;
use App\Kuafu\Order\Enum\CodeEnum;
use App\Kuafu\Order\Enum\OrderCacheEnum;
use App\Kuafu\Order\Enum\OrderCodeEnum;
use App\Kuafu\Order\Exceptions\OrderException;
use App\Kuafu\Order\Exceptions\OrderWaringException;
use App\Kuafu\Order\Jobs\MybankCalcOrderPriceJob;
use App\Kuafu\Order\Jobs\OrderPayPolling;
use App\Kuafu\Order\Jobs\PayNotifyJob;
use App\Kuafu\Order\Model\ConsumerOrder;
use App\Kuafu\Order\Model\OrderCouponSplitModel;
use App\Kuafu\Order\Model\OrderDetailSplitModel;
use App\Kuafu\Order\Model\OrderExternalSplitModel;
use App\Kuafu\Order\Model\OrderSplitModel;
use App\Kuafu\Pay\BasePay;
use App\Kuafu\Pay\Enum\BasePayEnum;
use App\Kuafu\Pay\Enum\PayCodeEnum;
use App\Kuafu\Pay\Exceptions\PayException;
use App\Kuafu\Pay\Model\PayStreamMappingModel;
use App\Kuafu\Pay\Model\PayStreamModel;
use App\Kuafu\Pay\Service\PayService;
use App\Kuafu\Pay\Service\ShopPayService;
use App\Kuafu\Shop\Service\ShopDistributionService;
use App\Kuafu\Shop\Service\ShopService;
use App\Kuafu\Wechat\Service\WechatSendMessageService;
use App\Library\FeiShu\SendFs;
use App\Support\AppletEncrypt;
use CodeItNow\BarcodeBundle\Utils\QrCode;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

/**
 * 订单支付服务V2
 *
 * Class OrderPayService
 * @package App\Kuafu\Order\Service
 */
class OrderPay extends OrderBaseSplitService
{
    private bool $isSendMQ = true; // 是否推送 MQ

    private array $userInfo = [
        'userId'   => 0,
        'openId'   => '',
        'platform' => 0,
        'unionid'  => ''
    ];

    /**
     * 设置用户信息
     * @param array $data
     */
    public function setUserInfo(array $data)
    {
        $this->userInfo = [
            'userId'     => $data['userId'] ?? 0,
            'openId'     => $data['openId'] ?? '',
            'platformId' => $data['platformId'] ?? 0,
            'unionid'    => $data['unionid'] ?? ''
        ];
    }

    /**
     * 支付数据
     * @var array
     */
    public array $payData = [];

    public array $payResult = [];

    /**
     * @var string 订单支付流水
     */
    public string $payNo = '';

    /**
     * 条形码支付
     */
    public function barPay()
    {
        $this->payData['payPrice'] = $this->payData['payPrice'] ?? $this->getOrderInfo()->shouldPrice;

        Log::channel('order')->info('OrderPay_barPay', [
            'orderInfo' => $this->getOrderInfo()
        ]);

        try {
            // 付款
            $result = PayService::sFaceToFacePay(
                (int)$this->shopId,
                (int)$this->orderId,
                $this->payData['payPrice'],
                '夸父点餐订单',
                $this->payData['payAuthCode'],
                PayStreamModel::SYS_TYPE_RMS_MEAL
            );

            // 判断支付状态
            switch ($result['payStatus']) {
                case BasePayEnum::TRADE_STATUS_OK:
                    $this->successV2();
                    $this->finish();
                    break;
                case BasePayEnum::TRADE_STATUS_WAIT:
                    //x 分钟自动取消订单
                    OrderPayPolling::dispatch(
                        $this->brandId,
                        $this->shopId,
                        $this->orderId,
                        $result['payNo']
                    )->onQueue(OrderPayPolling::QUEUE_NAME)->delay(CodeEnum::ORDER_CANCEL_TIME_MINUS * 60);
                default:
            }
        } catch (PayException $exception) {
            Log::debug('订单支付失败');
            $this->unLockOrder(CodeEnum::ORDER_LOCK_TYPE_ORDER_PAY);
            return [
                'code' => $exception->code,
                'msg'  => $exception->message
            ];
        }

        return [
            'status' => $result['payStatus'] ?? 0,
            'payNo'  => $result['payNo'] ?? 0
        ];
    }

    /**
     * 校验富友支付配置是否绑定
     *
     * @throws PayException
     */
    public function checkBindFuYou()
    {
        $payConfig = ShopPayService::getPayConfigCache($this->shopId, PayStreamModel::PAY_CHANNEL_FY);

        if (!$payConfig) {
            throw new PayException(PayCodeEnum::ERR_PAY_CONFIG_EMPTY, '支付配置为空, 请联系门店重新下单');
        }
    }

    /**
     * 现金支付
     */
    public function cashPay()
    {
        $this->payData['payPrice'] = $this->payData['payPrice'] ?? $this->getOrderInfo()->shouldPrice;

        Log::info('订单被扫支付', [
            'orderId'     => $this->orderId,
            'payPrice'    => $this->payData['payPrice'] ?? 0,
            'shouldPrice' => $this->getOrderInfo()->shouldPrice
        ]);

        if ($this->payData['payPrice'] == 0) {
            // 如果是 0 元设置成结清
            $this->updatePayData([
                'payMethod' => CodeEnum::ORDER_PAY_CHANNEL_ZERO_PAY,
            ]);

            $result = [
                'payStatus' => BasePayEnum::TRADE_STATUS_OK
            ];

        } else {
            $result = PayService::cashPay(
                (int)$this->shopId,
                (int)$this->orderId,
                $this->payData['payPrice']
            );
        }

        $this->payNo = $result['payNo'] ?? '';

        return [
            'status' => $result['payStatus'] ?? 0,
            'payNo'  => $result['payNo'] ?? ''
        ];
    }

    /**
     * 支付方式 - 支付成功
     */
    public function successPay()
    {
        return [
            'status' => BasePayEnum::TRADE_STATUS_OK
        ];
    }

    /**
     * 小程序订单支付
     *
     * @return array
     * @throws OrderException
     */
    public function genAppletPay()
    {
        $this->checkOrderHasPayed();

        $lock = $this->lockOrder(120, CodeEnum::ORDER_LOCK_TYPE_ORDER_PAY); // 2 分钟内不允许 再次支付

        // 订单已经上锁了
        if (!$lock) {
            $ttl = $this->getLockTime(CodeEnum::ORDER_LOCK_TYPE_ORDER_PAY);
            throw new OrderException(OrderCodeEnum::ERR_ORDER_HAS_BAR_PAYING,
                OrderCodeEnum::CODE_TEXT[OrderCodeEnum::ERR_ORDER_HAS_BAR_PAYING] . $ttl . '秒后再试');
        }

        // 判断支付金额是否是 0
        $shouldPayPrice = $this->orderInfo->shouldPrice;

        if ($shouldPayPrice != 0) {
            // 创建支付
            try {
                Log::info('用户下单支付前数据', [
                    'orderId' => $this->orderId,
                    'openId'  => $this->userInfo['openId']
                ]);
                $result = PayService::sMiniPay(
                    (int)$this->shopId,
                    (int)$this->orderId,
                    $shouldPayPrice,
                    '夸父点餐订单',
                    $this->userInfo['openId'] ?? ''
                );

                Log::info('用户下单支付后数据', [
                    'orderId' => $this->orderId,
                    'openId'  => $this->userInfo['openId'],
                    'result'  => $result
                ]);

                OrderPayPolling::dispatch(
                    $this->brandId,
                    $this->shopId,
                    $this->orderId,
                    $result['payNo'],
                )->onQueue(OrderPayPolling::QUEUE_NAME)->delay(CodeEnum::ORDER_CANCEL_TIME_MINUS * 60);

                // 生成队列查询订单状态
            } catch (OrderException $exception) {
                Log::debug('订单支付失败');
                $this->unLockOrder(CodeEnum::ORDER_LOCK_TYPE_ORDER_PAY);
            }
        } else {

            $this->successV2();
            $this->finish();
            $result['wx'] = '';
        }


        return [
            'payConfig' => $result['wx']
        ];
    }

    /**
     * 生成小程序二维码
     */
    public function genAppletQrCode()
    {
        //订单号生成加密token且只能使用一次
        $token = AppletEncrypt::getInstance()->encryptOrderData($this->orderId, CodeEnum::QR_CODE_KEY);
        //生成token保存到redis
        Redis::setex(OrderCacheEnum::PREFIX_ORDER_TOKEN . $this->orderId, CodeEnum::QR_CODE_EXPIRE_TIME, $token);
        // 微信小程序码方案
//        $path   = config('wechat.orderInfoPage') . "?orderToken=$token";
//        $data   = array("path" => $path, "width" => 150);
//        $qrCode = WechatService::createQrCode(CodeEnum::QR_CODE_ONE, $data);
//        $isNew = ShopAppletService::checkIsNew($this->shopId);
//        if ($isNew) {
        $url = config('other.QR_URL') . '/new-order/';
//        } else {
//            $url = config('other.QR_URL') . '/order/';
//        }
        // 可兼容的码方案
        $path   = $url . $token . '?shopId=' . $this->shopId;
        $qrCode = (new QrCode())->setText($path)->setImageType(QrCode::IMAGE_TYPE_PNG);
        $qrCode = 'data:' . $qrCode->getContentType() . ';base64,' . $qrCode->generate();

        return ['imageUrl' => $qrCode];
    }

    /**
     * 支付数据
     *
     * @param array $data
     */
    public function setPayData($data)
    {
        // 校验支付数据
        if (empty($data['payMethod'])) {
            throw new OrderException(OrderCodeEnum::ERR_ORDER_PAY_METHOD_ERR);
        }

        if (!empty($data['payAuthCode'])) {
            $data['payMethod'] = BasePay::checkAuthCode($data['payAuthCode']);
        }

        if (!empty($data['payPrice']) && $data['payPrice'] < 0) {
            throw new OrderException(OrderCodeEnum::ERR_ORDER_DB_ADD);
        }

        $this->payData = $data;
    }

    /**
     * 更新支付数据
     *
     * @param $data
     */
    public function updatePayData($data)
    {
        $org = $this->payData;
        foreach ($data as $key => $one) {
            $org[$key] = $one;
        }
        $this->payData = $org;
    }

    /**
     * 订单支付完成 执行的方法 前
     */
    public function beforeSuccess()
    {
        $order = $this->getOrderInfo(true);

        Log::channel('order')->debug('orderPay-success_Start', [
            'orderId'     => $order->orderId,
            'orderStatus' => $order->orderStatus,
            'payStatus'   => $order->payStatus,
            'payChannel'  => $order->payChannel,
            'payPrice'    => $order->payPrice
        ]);
    }

    /**
     * 订单支付完成 执行中的方法
     * @throws \App\Kuafu\CustomerCoupon\Exceptions\CustomerCouponException
     */
    public function OnSuccess()
    {
        $order              = $this->getOrderInfo();
        $order->orderId     = (int)$order->orderId;
        $order->orderStatus = CodeEnum::ORDER_STATUS_FINISHED;
        $order->payStatus   = CodeEnum::ORDER_PAY_STATUS_PAYED;
        $order->payChannel  = $this->payData['payMethod'];

        // 核销 订单的所有优惠券
        OrderCouponSplitModel::suffix($this->shopId)->verificationOrderCoupon((int)$order->orderId, $this->shopId);

        Log::channel('order')->debug('orderPay-success_this_orderId', [
            'orderId'     => $order->orderId,
            'thisOrderId' => $this->orderId,
        ]);

        $order->payPrice     = self::getOrderPayPrice();
        $order->realPayPrice = $order->payPrice + $order->couponCostPrice;
        // 判断订单是否是全部退款如果是,改成部分退款
        if ($order->originalPrice > 0 && $order->refundStatus == CodeEnum::ORDER_REFUND_STATUS_ALL) {
            $order->refundStatus = CodeEnum::ORDER_REFUND_STATUS_PART;
        }
        // 支付完成后,应付金额 = 0
        $order->shouldPrice = 0;

        Log::channel('order')->debug('orderPay-success_getOrderTotalPrice', [
            'orderId'      => $order->orderId,
            'orderStatus'  => $order->orderStatus,
            'payStatus'    => $order->payStatus,
            'payChannel'   => $order->payChannel,
            'payPrice'     => $order->payPrice,
            'realPayPrice' => $order->realPayPrice,
        ]);


        // 如果是试吃 修改订单的 优惠
        // TODO 整理细化
        if ($order->payChannel == CodeEnum::ORDER_PAY_CHANNEL_TRY_TACK) {
            /**
             * Order
             */
            Log::channel('order')->debug('orderPay-beforeSuccess_shiChi_0', [
                'orderId'           => $order->orderId,
                'discountPrice'     => $order->discountPrice,
                'shouldPrice'       => $order->shouldPrice,
                'payPrice'          => $order->payPrice,
                'couponPrice'       => $order->couponPrice,
                'couponCostPrice'   => $order->couponCostPrice,
                'realDiscountPrice' => $order->realDiscountPrice,
                'realPayPrice'      => $order->realPayPrice,
            ]);

            $order->discountPrice     = $order->originalPrice;
            $order->shouldPrice       = 0;
            $order->payPrice          = 0;
            $order->couponPrice       = 0;
            $order->couponCostPrice   = 0;
            $order->realDiscountPrice = $order->originalPrice;
            $order->realPayPrice      = 0;

            Log::channel('order')->debug('orderPay-beforeSuccess_shiChi_1', [
                'orderId'       => $order->orderId,
                'discountPrice' => $order->discountPrice,
                'payPrice'      => $order->payPrice,
            ]);

            /**
             * Order Detail
             */
            OrderDetailSplitModel::suffix($this->shopId)
                                 ->updateOrderDetailDataByOrderId((int)$order->orderId, [
                                     'totalDiscountPrice' => DB::raw('originalPrice'),
                                     'shouldUnitPrice'    => 0,
                                     'payPrice'           => 0,
                                     'freeNum'            => 0,  // 试吃赠菜改为 0
                                     'discountPrice'      => 0,  // 试吃单菜优惠为 0
                                     'discountType'       => 0,  // 试吃单菜优惠为 0
                                     'discountNum'        => 0,  // 试吃单菜优惠为 0
                                 ]);
        }

        // 第一次更新数据库
        $order->save();

        // 查询
        $couponPackageOrder = OrderExternalSplitModel::suffix($this->shopId)
                                                     ->query()
                                                     ->where('orderId', (int)$order->orderId)
                                                     ->where('type', CodeEnum::ORDER_EXTERNAL_TYPE_COUPON_PACKAGE)
                                                     ->first();

        // 判断是否购买券包了
        if (!empty($couponPackageOrder)) {

            Log::channel('order')->debug('orderPay-couponPackage_send1');
            // 获取券包订单 ID
            $couponPackageOrderId = (int)$couponPackageOrder->extOrderId;
            // 获取券包的订单详情
            $couponPackageOrderInfo = CouponPackageOrderModel::query()
                                                             ->where('orderId', $couponPackageOrderId)
                                                             ->first();
            // 修改订单实付金额
            $order->payPrice     = OrderCalcService::setPriceNotNegative($order->payPrice - $couponPackageOrderInfo->payPrice);
            $order->realPayPrice = OrderCalcService::setPriceNotNegative($order->realPayPrice - $couponPackageOrderInfo->payPrice);


            Log::channel('order')->debug('orderPay-couponPackage_send2', [
                'orderId'           => $order->orderId,
                'packageId'         => $couponPackageOrderId,
                'orderPackageInfo'  => $couponPackageOrderInfo,
                'afterPayPrice'     => $order->payPrice,
                'afterRealPayPrice' => $order->realPayPrice,
            ]);


            // 获取订单所用的券包优惠券 列表
            $coulist     = OrderCouponSplitModel::suffix($this->shopId)
                                                ->getOrderCouponListByCouponSource((int)$order->orderId);
            $checkCoupon = [];
            if (!empty($coulist)) {
                $coulist->pluck('couponId')->map(function ($item) use (&$checkCoupon) {
                    $checkCoupon[$item] = 1;
                });
            }

            // 券销售状态
            CouponPackageOrderModel::paySuccess($couponPackageOrderId);

            // 推送券包
            $cp         = CouponPackageOrderModel::query()->find($couponPackageOrderId);
            $usedCoupon = CouponPackageService::finished($cp->couponPackageId, $cp->userId, $checkCoupon,
                $this->shopId, $couponPackageOrderId);
            // 回写 处理已经用过的优惠券
            foreach ($usedCoupon as $key => $cc) {
                $model = OrderCouponSplitModel::suffix($this->shopId)
                                              ->query()
                                              ->where('orderId', $order->orderId)
                                              ->where('couponId', $cc)
                                              ->where('customerCouponId', 0)
                                              ->first();

                $model->customerCouponId = $key;
                $model->save();
            }


            Log::channel('order')->debug('orderPay-couponPackage_send3', [
                'orderId' => $order->orderId
            ]);

        }
        // 第二次更新数据库


        // 判断是否是反结账状态
        if (!empty($this->payData['payEvent']) && $this->payData['payEvent'] == CodeEnum::ORDER_PAY_EVENT_REFUND) {
            $refund = new OrderRefund($this->brandId, $this->shopId, $order->orderId);
            $refund->updateOrderRefundV2();
        }
        $order->save();

        // 判断是否存在 userId
        if ($order->userId || $order->platformId) {
            ConsumerOrder::query()->updateOrCreate(
                [
                    'orderId' => $order->orderId
                ],
                [
                    'originalPrice'    => $order->originalPrice,
                    'payPrice'         => $order->payPrice,
                    'discountPrice'    => $order->discountPrice,
                    'orderStatus'      => $order->orderStatus,
                    'shouldPrice'      => $order->shouldPrice,
                    'orderShouldPrice' => $order->orderShouldPrice,
                    'payStatus'        => $order->payStatus,
                    'completeTime'     => time(),
                ]);

        }
    }

    /**
     * 订单支付完成 执行的方法 后
     */
    public function afterSuccess()
    {
        $order = $this->getOrderInfo(true);

        // 解锁订单
        $this->unLockOrder(CodeEnum::ORDER_LOCK_TYPE_ORDER_PAY);
        // 推送 MQTT 消息
        $this->sendMqtt();
        // 如果是反结账状态

        Log::channel('order')->debug('orderPay-success_last', [
            'orderId'     => $order->orderId,
            'orderStatus' => $order->orderStatus,
            'payStatus'   => $order->payStatus,
            'payChannel'  => $order->payChannel,
            'payPrice'    => $order->payPrice
        ]);

    }

    /**
     * 支付成功 V2
     * @return array
     */
    public function successV2()
    {
        try {
            // 订单支付成功 前置函数
            $this->beforeSuccess();

            // 订单支付成功 执行中的方法
            $this->OnSuccess();

            // 订单完成最后的收尾函数
            $this->afterSuccess();
        } catch (\Exception $exception) {
            throw new \Exception('订单支付回调报错了!!快检查!!', 0, $exception);
        }

    }

    /**
     * 完成订单
     */
    public function finish()
    {
        if ($this->orderInfo->orderStatus != CodeEnum::ORDER_STATUS_FINISHED) {
            $this->orderInfo->orderStatus = CodeEnum::ORDER_STATUS_FINISHED;

        }

        $this->orderInfo->completeTime = time();

        Log::channel('order')->debug('orderPay-finish', [
            'discountPrice' => $this->orderInfo->discountPrice,
            'payPrice'      => $this->orderInfo->payPrice
        ]);


        $this->orderInfo->save();
        $this->beforeFinish();
    }

    /**
     * 订单完成之后的操作
     */
    public function beforeFinish()
    {
        //订单完成 队列入队
        try {
            PayNotifyJob::dispatch(
                $this->shopId,
                $this->orderId
            )->onQueue(PayNotifyJob::$QUEUE_NAME);
        } catch (Exception $ex) {
            CommonService::fsLogException('【 队列入队 】【 支付回调 】', $ex,
                ['shopId' => $this->shopId, 'orderId' => $this->orderId], true);
        }

        //订单完成 队列入队
        try {
            MybankCalcOrderPriceJob::dispatch(
                $this->shopId,
                $this->orderId,
                CodeEnum::SOURCE_TYPE_SHOP
            )->onQueue(MybankCalcOrderPriceJob::$QUEUE_NAME);
        } catch (Exception $ex) {
            CommonService::fsLogException('【 队列入队 】【 网商堂食分账计算佣金 】', $ex,
                ['shopId' => $this->shopId, 'orderId' => $this->orderId], true);
        }

        try {
            // 微信消息推送
            $this->sendWechatMessage();

            if (!empty($this->orderInfo->distributionId)) {
                // 获取对应渠道信息
                self::updateAppletOrderDistribution();
            }

        } catch (\Exception $exception) {
            Log::channel('order')->error('BeforeFinish-ERROR', [
                'type'     => 'RMS_ORDER',
                'shopId'   => $this->shopId,
                'orderId'  => $this->orderId,
                'errorMsg' => $exception
            ]);
        }
    }


    private function updateAppletOrderDistribution()
    {
        $distributionInfo = ShopDistributionService::getEffectInfoById($this->orderInfo->distributionId);
        if (empty($distributionInfo)) {
            return;
        }

        // 计算抽佣金额
        $distributionAmount                  = bcmul($this->orderInfo->realPayPrice, ($distributionInfo->ratio / 100));
        $this->orderInfo->distributionPer    = $distributionInfo->ratio . '%';
        $this->orderInfo->distributionAmount = $distributionAmount;

        $this->orderInfo->save();
    }


    /**
     * POS 支付
     */
    public function posPay()
    {

    }

    /**
     * 发送 mqtt 消息
     */
    public function sendMqtt()
    {
        if (!$this->isSendMQ) {
            return;
        }
        (new MqttService($this->brandId, $this->shopId))->paySuccess(
            $this->orderId,
            $this->orderInfo->sourceType,
            $this->orderInfo->deliveryType
        );
    }

    /**
     * 发送 微信订单 消息
     */
    public function sendWechatMessage()
    {
        try {
            Log::info(
                'sendWechatMessage_logINfo', [$this->orderInfo]
            );
            $userId = $this->orderInfo->userId;
            if (!empty($userId)) {
                $userOpenId       = CustomerPlatformService::getUserFieldByUserId($userId, 1, ['openid']);
                $openid           = $userOpenId['openid'];
                $shopInfo         = ShopService::getShopInfo($this->shopId);
                $shopName         = $shopInfo['name'];
                $address          = $shopInfo['address'];
                $serialNum        = $this->orderInfo->serialNum;
                $orderCreatedTime = $this->orderInfo->createdAt;

                Log::info('sendWechatMessage', [
                    '$openid'           => $openid,
                    '$shopName'         => $shopName,
                    '$serialNum'        => $serialNum,
                    '$orderId'          => $this->orderId,
                    '$orderCreatedTime' => $orderCreatedTime,
                    '$address'          => $address
                ]);
                WechatSendMessageService::PayOrderSendMessage($openid, $shopName, $serialNum,
                    $this->orderId, $orderCreatedTime, $address, $shopInfo['id']);
            }
        } catch (\Exception $exception) {
            Log::error(
                'sendWechatMessage_error', [$exception]
            );
        }

    }

    /**
     * 校验订单是否已经支付
     */
    private function checkOrderHasPayed()
    {
        // 判断订单状态
        if ($this->orderInfo->payStatus == CodeEnum::ORDER_PAY_STATUS_PAYED) {
            throw new OrderException(OrderCodeEnum::ERR_ORDER_HAS_PAYED,
                OrderCodeEnum::CODE_TEXT[OrderCodeEnum::ERR_ORDER_HAS_PAYED]);
        }

        return $this;
    }

    /**
     * 请求支付后,订单归属问题
     */
    public function updateOrderPayInfo()
    {
        $orderInfo = OrderSplitModel::suffix($this->shopId)->query()
                                    ->where('orderId', $this->getOrderId(true))
                                    ->first();

        $orderInfo->platformId = $this->userInfo['unionid'];
        $orderInfo->userId     = $this->userInfo['userId'];

        ConsumerOrder::query()->where('orderId', $this->getOrderId(true))->update(
            [
                'userId'     => $orderInfo->userId,
                'platformId' => $orderInfo->platformId
            ]);

        $orderInfo->save();
    }

    /**
     * 获取三方优惠券用户所支付的金额
     *
     * return int
     */
    public function getOrderExtCouponUserPay(): int
    {
        $sum = OrderCouponExtSplitModel::suffix($this->shopId)->query()->where('orderId', $this->orderId)
                                       ->where('couponStatus', CouponExtEnum::COUPON_STATUS_USED)
                                       ->sum('userPay');

        return (int)$sum;

    }

    /**
     * 重置菜品的订单优惠
     *
     * @param object $order
     */
    public function resetOrderDetailDiscount(object $order)
    {

        // 当订单实收 > 订单原价 时, 取消所有折扣 按原价计算
        if (bccomp($order->payPrice, $order->originalPrice) >= 0) {
            $order->discountPrice = 0;
            $order->couponPrice   = 0;

            $orderDetail = $this->getOrderDetail();

            $detailIds = array_column($orderDetail, 'id');

            OrderDetailSplitModel::suffix($this->shopId)
                                 ->updateOrderDetailData($detailIds, [
                                     'totalDiscountPrice'  => 0,
                                     'orderDiscountPrice'  => 0,
                                     'couponDiscountPrice' => 0,
                                     'discountPrice'       => 0,
                                     'shouldUnitPrice'     => DB::raw('originalUnitPrice'),
                                     'payPrice'            => DB::raw('originalPrice'),
                                     'discountType'        => 0,
                                     'discountNum'         => 0
                                 ]);

        }
    }

    /**
     * 获取用户支付总金额 = 支付流水 - 退款流水 - 券包支付应付金额
     *
     * @return int
     */
    public function getOrderPayPrice(): int
    {
        $payPrice    = self::getOrderPayStreamPrice($this->orderId);
        $refundPrice = OrderRefund::getOrderRefundPrice($this->orderId, [], PayStreamModel::PAID_IN_YES);

        return $payPrice - $refundPrice;
    }

    /**
     * 获取订单总 实收 支付流水总额getOrderPayPrice
     *
     * @param string $orderId 订单号
     * @param array $payChannel 支付渠道[]
     * @return int
     */
    public static function getOrderPayStreamPrice(
        string $orderId,
        array $payChannel = [],
        $isPaidIn = PayStreamModel::PAID_IN_YES
    ): int {
        $mappings = PayStreamMappingModel::getDataByBizId($orderId);
        $shopId   = $mappings['shopId'];
        $sysType  = $mappings['sysType'];

        return PayStreamModel::suffix($shopId, $sysType)
                             ->where('orderId', (int)$orderId)
                             ->where('payStatus', PayStreamModel::PAY_STATUS_1)
                             ->where('sysType', PayStreamModel::SYS_TYPE_RMS_MEAL)
                             ->when($isPaidIn != PayStreamModel::PAID_IN_ALL, function ($query) use ($isPaidIn) {
                                 $query->where('isPaidIn', $isPaidIn);
                             })
                             ->when(!empty($payChannel), function ($query) use ($payChannel) {
                                 $query->whereIn('payChannel', $payChannel);
                             })
                             ->sum('payPrice');
    }


    /**
     * 获取订单总支付流水
     *
     * @param string $orderId
     * @param array $payChannel
     */
    public static function getOrderPayStreamList(string $orderId, array $payChannel = [])
    {
        $mappings = PayStreamMappingModel::getDataByBizId($orderId);
        $shopId   = $mappings['shopId'];
        $sysType  = $mappings['sysType'];

        return PayStreamModel::suffix($shopId, $sysType)
                             ->where('orderId', $orderId)
                             ->where('payStatus', PayStreamModel::PAY_STATUS_1)
                             ->where('sysType', PayStreamModel::SYS_TYPE_RMS_MEAL)
                             ->where('isPaidIn', PayStreamModel::PAID_IN_YES)
                             ->when(!empty($payChannel), function ($query) use ($payChannel) {
                                 $query->whereIn('payChannel', $payChannel);
                             })
                             ->get();
    }

    /**
     * 订单支付上锁
     *
     * @param $method int|string 支付方式
     * @throws OrderException
     */
    public function lockPay($method)
    {
        $tag  = CodeEnum::ORDER_LOCK_TYPE_ORDER_PAY_COMMON . $method;
        $lock = $this->lockOrder(6, $tag);
        // 订单已经上锁了
        if (!$lock) {
            $ttl = $this->getLockTime($tag);

            throw new OrderWaringException(OrderCodeEnum::ERR_ORDER_HAS_BAR_PAYING,
                OrderCodeEnum::CODE_TEXT[OrderCodeEnum::ERR_ORDER_HAS_BAR_PAYING] . $ttl . '秒后再试');
        }
    }


    /**
     * 切换富友子支付渠道同步到订单支付方式
     *
     * @param int $fyChileChannel
     * @return int
     */
    public static function switchFyChileChannel2OrderPayChannel(int $fyChileChannel): int
    {
        switch ($fyChileChannel) {
            case PayStreamModel::PAY_CHANNEL_CHILD_ALI:
                $payChannel = CodeEnum::ORDER_PAY_CHANNEL_ALIPAY;
                break;
            case PayStreamModel::PAY_CHANNEL_CHILD_WX:
                $payChannel = CodeEnum::ORDER_PAY_CHANNEL_WECHAT;
                break;
            case PayStreamModel::PAY_CHANNEL_CHILD_UNION_PAY:
                $payChannel = CodeEnum::ORDER_PAY_CHANNEL_UNION_PAY;
                break;
            default:
                $payChannel = CodeEnum::ORDER_PAY_CHANNEL_ALIPAY;
        }

        return $payChannel;
    }

    public function setIsSendMQ(bool $isSendMQ)
    {
        $this->isSendMQ = $isSendMQ;
    }
}
